﻿using System;
using System.Text;
using MSGeoCoder;

namespace GeoCode.Core
{
    /// <summary>
    /// 
    /// </summary>
    /// <remarks></remarks>
    public class Address
    {
        /// <summary>
        /// 
        /// </summary>
        private AddressAccuracy _accuracy;
        /// <summary>
        /// 
        /// </summary>
        private string _city;
        /// <summary>
        /// 
        /// </summary>
        private Location _coordinates;
        /// <summary>
        /// 
        /// </summary>
        private string _country;
        /// <summary>
        /// 
        /// </summary>
        private string _postalCode;
        /// <summary>
        /// 
        /// </summary>
        private string _state;
        /// <summary>
        /// 
        /// </summary>
        private string _street;

        /// <summary>
        /// Initializes a new instance of the <see cref="T:System.Object"/> class.
        /// </summary>
        /// <remarks></remarks>
        public Address()
        {
            _coordinates = Location.Empty;
            _accuracy = AddressAccuracy.Unknown;
        }

        /// <summary>
        /// Gets or sets the street.
        /// </summary>
        /// <value>The street.</value>
        /// <remarks></remarks>
        public string Street
        {
            get { return _street ?? ""; }
            set { _street = value; }
        }

        /// <summary>
        /// Gets or sets the city.
        /// </summary>
        /// <value>The city.</value>
        /// <remarks></remarks>
        public string City
        {
            get { return _city ?? ""; }
            set { _city = value; }
        }

        /// <summary>
        /// Gets or sets the state.
        /// </summary>
        /// <value>The state.</value>
        /// <remarks></remarks>
        public string State
        {
            get { return _state ?? ""; }
            set { _state = value; }
        }

        /// <summary>
        /// Gets or sets the postal code.
        /// </summary>
        /// <value>The postal code.</value>
        /// <remarks></remarks>
        public string PostalCode
        {
            get { return _postalCode ?? ""; }
            set { _postalCode = value; }
        }

        /// <summary>
        /// Gets or sets the country.
        /// </summary>
        /// <value>The country.</value>
        /// <remarks></remarks>
        public string Country
        {
            get { return _country ?? ""; }
            set { _country = value; }
        }

        /// <summary>
        /// Gets or sets the coordinates.
        /// </summary>
        /// <value>The coordinates.</value>
        /// <remarks></remarks>
        public Location Coordinates
        {
            get { return _coordinates; }
            set { _coordinates = value; }
        }

        /// <summary>
        /// Gets the accuracy.
        /// </summary>
        /// <remarks></remarks>
        public AddressAccuracy Accuracy
        {
            get { return _accuracy; }
        }

        /// <summary>
        /// Gets or sets the lat lon box.
        /// </summary>
        /// <value>The lat lon box.</value>
        /// <remarks></remarks>
        public Box LatLonBox { get; set; }

        /// <summary>
        /// Distances the between.
        /// </summary>
        /// <param name="address">The address.</param>
        /// <returns></returns>
        /// <remarks></remarks>
        public virtual Distance DistanceBetween(Address address)
        {
            return Coordinates.DistanceBetween(address.Coordinates);
        }

        /// <summary>
        /// Distances the between.
        /// </summary>
        /// <param name="address">The address.</param>
        /// <param name="units">The units.</param>
        /// <returns></returns>
        /// <remarks></remarks>
        public virtual Distance DistanceBetween(Address address, DistanceUnits units)
        {
            return Coordinates.DistanceBetween(address.Coordinates, units);
        }

        /// <summary>
        /// Changes the location.
        /// </summary>
        /// <param name="coordinates">The coordinates.</param>
        /// <param name="accuracy">The accuracy.</param>
        /// <remarks></remarks>
        public virtual void ChangeLocation(Location coordinates, AddressAccuracy accuracy)
        {
            this._coordinates = coordinates;
            this._accuracy = accuracy;
        }

        /// <summary>
        /// Returns a <see cref="System.String"/> that represents this instance.
        /// </summary>
        /// <returns>A <see cref="System.String"/> that represents this instance.</returns>
        /// <remarks></remarks>
        public override string ToString()
        {
            var address = new StringBuilder();

            bool hasStuff = false;

            if (!String.IsNullOrEmpty(_street))
            {
                address.Append(_street);
                hasStuff = true;
            }

            if (!String.IsNullOrEmpty(_city))
            {
                if (hasStuff)
                    address.Append(", ");
                address.Append(_city);
                hasStuff = true;
            }

            if (!String.IsNullOrEmpty(_state))
            {
                if (hasStuff)
                    address.Append(", ");
                address.Append(_state);
                hasStuff = true;
            }

            if (!String.IsNullOrEmpty(_postalCode))
            {
                if (hasStuff)
                    address.Append(" ");
                address.Append(_postalCode);
                hasStuff = true;
            }

            if (!String.IsNullOrEmpty(_country))
            {
                if (hasStuff)
                    address.Append(", ");
                address.Append(_country);
            }

            return address.ToString();
        }
    }
}